package com.ruoyi.thirdpart.service.impl;
import com.github.binarywang.wxpay.bean.request.WxPayRefundRequest;
import com.github.binarywang.wxpay.bean.request.WxPayUnifiedOrderRequest;
import com.github.binarywang.wxpay.bean.result.WxPayRefundResult;
import com.github.binarywang.wxpay.config.WxPayConfig;
import com.github.binarywang.wxpay.constant.WxPayConstants;
import com.github.binarywang.wxpay.service.WxPayService;
import com.github.binarywang.wxpay.service.impl.WxPayServiceImpl;
import com.github.binarywang.wxpay.exception.WxPayException;

import com.ruoyi.common.constant.UserConstants;
import com.ruoyi.market.domain.ConfigPay;
import com.ruoyi.market.domain.ConfigProgram;
import com.ruoyi.market.mapper.ConfigPayMapper;
import com.ruoyi.market.mapper.ConfigProgramMapper;
import com.ruoyi.thirdpart.service.IBizWechatPayService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
import org.springframework.stereotype.Service;

import java.net.InetAddress;


@ConditionalOnClass(WxPayService.class)
/**
 * 支付 业务层处理
 * 
 * @author ruoyi
 */
@Service
public class BizWechatPayServiceImpl implements IBizWechatPayService
{
    // 接口前缀
    private final String api_pre = "/prod-api";

    @Autowired
    private ConfigPayMapper configPayMapper;

    @Autowired
    private ConfigProgramMapper configProgramMapper;

    public WxPayService wxPayService(String payType, String shopId) {
        WxPayConfig payConfig = new WxPayConfig();
        ConfigPay configPay = configPayMapper.selectConfigPayByShopId(shopId);
        ConfigProgram configProgram = configProgramMapper.selectConfigProgramByShopId(shopId);
        if (payType.equals(UserConstants.PAY_TYPE_WX_OFFICIAL_ACCOUNT)) {
            payConfig.setAppId(configProgram.getOfficialAppId());
        }
        if (payType.equals(UserConstants.PAY_TYPE_WX_MINI_PROGRAM)) {
            payConfig.setAppId(configProgram.getWxMpAppId());
        }
        payConfig.setMchId(configPay.getWxMchId());
        payConfig.setMchKey(configPay.getWxMchSecret());
        payConfig.setKeyPath(configProgram.getOfficialDomain() + api_pre + configPay.getWxTwelveCertBook());
        payConfig.setPrivateKeyPath(configProgram.getOfficialDomain() + api_pre + configPay.getWxKeyBook());
        payConfig.setPrivateCertPath(configProgram.getOfficialDomain() + api_pre + configPay.getWxPemCertBook());
        // 可以指定是否使用沙箱环境
        payConfig.setUseSandboxEnv(false);
        payConfig.setSignType("MD5");

        WxPayService wxPayService = new WxPayServiceImpl();
        wxPayService.setConfig(payConfig);
        return wxPayService;
    }

    /**
     * 创建微信支付订单
     *
     * @param productTitle 商品标题
     * @param outTradeNo   订单号
     * @param totalFee     总价
     * @param openId       openId
     * @param payType      支付方式
     * @param financeType  财务类型 - 订单 礼物 充值
     * @param shopId      店铺Id
     * @return
     */
    @Override
    public Object createOrder(String productTitle, String outTradeNo, Integer totalFee, String openId,
                              String payType, String financeType, String shopId) {
        try {
            ConfigProgram configProgram = configProgramMapper.selectConfigProgramByShopId(shopId);
            WxPayUnifiedOrderRequest request = new WxPayUnifiedOrderRequest();
            // 支付描述
            request.setBody(productTitle);
            // 订单号
            request.setOutTradeNo(outTradeNo);
            // 请按照分填写
            request.setTotalFee(totalFee);
            // 小程序需要传入 openid
            request.setOpenid(openId);
            // 回调链接 --- 实际就是微信要调用你的接口，不是前端页面地址
            request.setNotifyUrl(configProgram.getOfficialDomain() + api_pre + "/thirdpart/pay/wxPayCallback/" + payType + "/" + financeType + "/" + shopId);
            // 终端IP.
            request.setSpbillCreateIp(InetAddress.getLocalHost().getHostAddress());
            // 设置类型为JSAPI
            request.setTradeType(WxPayConstants.TradeType.JSAPI);
            // 一定要用 createOrder 不然得自己做二次校验
            Object order = wxPayService(payType, shopId).createOrder(request);
            return order;
        } catch (Exception e) {
            System.out.println(" ========  微信createOrder 方法异常 ======== ");
            System.out.println(e);
            return null;
        }

    }

    /**
     * 微信退款
     *
     * @param tradeNo 订单号
     * @param totalFee 总价
     * @param payType      支付方式
     * @param financeType  财务类型 - 订单 礼物 充值
     * @param shopId      店铺Id
     * @return
     */
    @Override
    public WxPayRefundResult wxRefund(String tradeNo, Integer totalFee, String payType, String financeType, String shopId) {
        ConfigProgram configProgram = configProgramMapper.selectConfigProgramByShopId(shopId);
        WxPayRefundRequest wxPayRefundRequest = new WxPayRefundRequest();
        // 商户订单号-out_trade_no  微信支付订单号-transaction_id  transaction_id和out_trade_no必须二选一进行传参。
        wxPayRefundRequest.setOutTradeNo(tradeNo);
        wxPayRefundRequest.setOutRefundNo(String.valueOf(System.currentTimeMillis()));
        wxPayRefundRequest.setTotalFee(totalFee);
        wxPayRefundRequest.setRefundFee(totalFee);
        wxPayRefundRequest.setNotifyUrl(configProgram.getOfficialDomain() + api_pre + "/thirdpart/pay/wxRefundCallback/" + payType + "/" + financeType + "/" + shopId);
        try {
            WxPayRefundResult refund = wxPayService(payType, shopId).refundV2(wxPayRefundRequest);
            if (refund.getReturnCode().equals("SUCCESS") && refund.getResultCode().equals("SUCCESS")) {
                return refund;
            }

        } catch (WxPayException e) {
            System.out.println("========= 微信退款异常 =========");
            System.out.println(e);
            e.printStackTrace();
        }
        return null;
    }
}
